package com.atguigu.gmall.item.controller;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author lsj
 * @create 2021-08-18 10:42
 *
 *  分布式锁 分布式集合
 */
@Slf4j
@RestController
public class LockTestController {

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    ThreadPoolExecutor executor;

    List<String> myTask = new ArrayList<>();  //任务打印的顺序


    /**
     *     core: 2
     *     max:  5
     *     keepalive: 60000
     *     queue-length: 10
     *  视觉效果：
     *    1、提交的任务，先开core线程处理，core饱满
     *    2、提交的任务，先入队
     *    3、队列满员以后，开到max
     *    4、max优先处理刚进来的新请求。处理完成后剩下的任务从队列拿
     *
     *  1、同步队列： new SynchronousQueue<>(true),
     *      队列的长度是0， 先开到核心，新的任务进来，再开到最大，任务超过最大线程，使用拒绝策略
     *  2、有界队列：
     *      new LinkedBlockingQueue<>(10),
     *      队列长度是指定的，先开到核心，新的任务进来，先入队，超过最大，开线程处理新的，
     *      新的都处理完（处理队列里面的），如果一直提交新的，就会拒绝策略
     *  3、无界队列： 设置的Max就是失效的
     *      长度无限
     *  4、优先级队列：
     *     new PriorityBlockingQueue<>(),  任务可以设置优先级；
     *     长度无限，按照优先级执行。
     *
     *
     * @return
     */

    @GetMapping("/execute")
    public String testThreadPool(){


//        CompletableFuture.runAsync(() -> {
//
//
//            log.info("线程正在执行..." + Thread.currentThread().getName());
//            try {
//                Thread.sleep(20000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            log.info("线程完成..." + Thread.currentThread().getName());
//        }, executor);
//        CompletableFuture.runAsync(() -> {
//
//            log.info("线程正在执行..." + Thread.currentThread().getName());
//            try {
//                Thread.sleep(20000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            log.info("线程完成..." + Thread.currentThread().getName());
//        }, executor);
        String substring = UUID.randomUUID().toString().substring(0, 5);
        myTask.add(substring);
        executor.submit(()->{
            log.info("线程正在执行..." + Thread.currentThread().getName()+"打印："+substring);
            try {
                Thread.sleep(10000);
                Thread.currentThread().setPriority(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });


        String substring2 = UUID.randomUUID().toString().substring(0, 5);
        myTask.add(substring2);
        executor.submit(()->{
            log.info("线程正在执行..." + Thread.currentThread().getName()+"打印："+substring2);
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        int size = executor.getQueue().size();
        int activeCount = executor.getActiveCount();

        return "任务已提交：当前排队的任务："+size+";  当前活动的任务："+activeCount+"</br>"+
                "任务提交顺序："+myTask;
    }


    @SneakyThrows
    @GetMapping("/write")
    public String readWrite(){

        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock");

        RLock lock = readWriteLock.writeLock();

        lock.lock();

        String s = UUID.randomUUID().toString();
        Thread.sleep(10000);
        redisTemplate.opsForValue().set("mymsg", s);
        lock.unlock();


        return s;
    }
    @GetMapping("/read")
    public String read(){
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock");

        RLock lock = readWriteLock.readLock();

        lock.lock();
        String mymsg = redisTemplate.opsForValue().get("mymsg");
        lock.unlock();

        return mymsg;

    }

    @GetMapping("/inittcc")
    public String tcc(int size){

        RSemaphore whsggdxtcc = redissonClient.getSemaphore("whsggdxtcc");
        whsggdxtcc.addPermits(size);
        return "whsggdxtcc 停车场有 "+size + "  个车位";
    }

    @GetMapping("/stopcar")
    public String stop() throws InterruptedException {
        RSemaphore whsggdxtcc = redissonClient.getSemaphore("whsggdxtcc");

        whsggdxtcc.acquire(1);  //从信号量里面拿一个




        return "停车成功...";
    }

    @GetMapping("/gocar")   //信号量
    public String start(){
        RSemaphore whsggdxtcc = redissonClient.getSemaphore("whsggdxtcc");


        whsggdxtcc.release(1);   //给信号量加值
        return "车开走了...";
    }


    //CountDownLatch 闭锁
    @GetMapping("/shenlong")
    public String shenlong() throws InterruptedException {
        RCountDownLatch zhsl = redissonClient.getCountDownLatch("zhsl");
        zhsl.trySetCount(7);  //需要七龙珠



        zhsl.await(); //等待龙珠集齐

        return "很大的神龙.....";
    }

    @GetMapping("/longzhu")
    public String longzhu(){
        RCountDownLatch zhsl = redissonClient.getCountDownLatch("zhsl");
        zhsl.countDown();

        return "收集了一颗龙珠";
    }

//
//    @GetMapping("/lock/hello")
//    public String hello(){
//
//        //执行业务逻辑
//
//
//
////    }

    /**
     * 以前用的 List，Map都在 内存中存的数据
     *
     * 分布式集合。
     *    1）、接下创建的集合里面存的数据都是在redis里面所有人都能用
     */
    @GetMapping("/pua")
    public String distributeCollection(){
        RMap<String, String> temp = redissonClient.getMap("temp");

//        Map  map = new HashMap();
//        map.put()
//        map.put()

        String string = UUID.randomUUID().toString();
        temp.put("hello",string);
        return string;
    }


    @GetMapping("/gea")
    public String getDistributeCollection(){
        RMap<String, String> temp = redissonClient.getMap("temp");
        String hello = temp.get("hello");
        return hello;
    }



}